home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / tkern10.zip / SRC\IO.C < prev    next >
Text File  |  1994-07-10  |  11KB  |  520 lines

  1. /*
  2.  *  This file forms part of "TKERN" - "Troy's Kernel for Windows".
  3.  *
  4.  *  Copyright (C) 1994  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * This module takes care of tkern file operations. Most of these
  23.  * get passed on to tkfmangr so that files can be inherited by
  24.  * child processes in tkern.
  25.  */
  26.  
  27. #include <windows.h>
  28. #include <toolhelp.h>
  29. #include <stdlib.h>
  30. #include <memory.h>
  31. #include <string.h>
  32. #include <alloc.h>
  33. #include <stdarg.h>
  34. #include <errno.h>
  35. #include <ctype.h>
  36. #include <dir.h>
  37. #include <sys/tfile.h>
  38. #include <sys/task.h>
  39. #include <sys/ioctl.h>
  40. #include <sys/wait.h>
  41. #include <sys/tkern.h>
  42.  
  43. struct    tfile    _files[TNFILE];
  44. static    HGLOBAL    hTFMem = 0;
  45. struct    tfunc    *ptf = 0;
  46.  
  47. static    int
  48. find_location(    struct task *pt,
  49.         int    *fd,
  50.         int    *ifd)
  51. {
  52.     for (*ifd = 0; *ifd < TNFILE; (*ifd)++)
  53.     {
  54.         if (!_files[*ifd].tf_cnt)
  55.             break;
  56.     }
  57.     if (*ifd == TNFILE)
  58.     {
  59.         pt->nError = EMFILE;
  60.         return -1;
  61.     }
  62.     for (*fd = 0; *fd < UFILE_MAX; (*fd)++)
  63.     {
  64.         if (pt->files[*fd] == -1)
  65.             break;
  66.     }
  67.     if (*fd == UFILE_MAX)
  68.     {
  69.         pt->nError = EMFILE;
  70.         return -1;
  71.     }
  72.     return 0;
  73. }
  74.  
  75.  
  76. int far _export
  77. tkern_open(    char const *pchFile,
  78.         int    nMode,
  79.         int    nAccess)
  80. {
  81.     int    iDevice;
  82.     int    id;
  83.     int    fd;
  84.     int    ifd;
  85.     char    const *c;
  86.     struct task *pt;
  87.     BOOL    bFile;
  88.  
  89.     pt = GetTaskInfo();
  90.     ptf->iTask = (pt - _tasks);
  91.     if (!strncmp(pchFile, "\\dev\\", 5) ||
  92.         !strncmp(pchFile, "/dev/", 5))
  93.     {
  94.         bFile = FALSE;
  95.         strcpy(ptf->achFile, pchFile + 5);
  96.         iDevice = SendMessage(hwndManager, TKWM_GETDEVNO, 0, (LPARAM) ptf);
  97.         pchFile += 5;
  98.         if ((c = strchr(pchFile, '/')) != 0)
  99.             pchFile = c + 1;
  100.     }
  101.     else
  102.     {
  103.         bFile = TRUE;
  104.         strcpy(ptf->achFile, "file");
  105.         iDevice = SendMessage(hwndManager, TKWM_GETDEVNO, 0, (LPARAM) ptf);
  106.     }
  107.  
  108.     if (find_location(pt, &fd, &ifd) == -1)
  109.         return -1;
  110.  
  111.     ptf->iDevice = iDevice;
  112.     ptf->iTask = (pt - _tasks);
  113.     if (bFile)
  114.     {
  115.         if (isalpha(pchFile[0]) && pchFile[1] == ':')
  116.         {
  117.             if (pchFile[2] == '\\')
  118.             {
  119.                 strcpy(ptf->achFile, pchFile);
  120.             }
  121.             else
  122.             {
  123.                 strncpy(ptf->achFile, pchFile, 2);
  124.                 getcurdir(toupper(pchFile[0]), ptf->achFile + 2);
  125.                 if (ptf->achFile[strlen(ptf->achFile) - 1] != '\\')
  126.                     strcat(ptf->achFile, "\\");
  127.                 strcat(ptf->achFile, pchFile + 2);
  128.             }
  129.         }
  130.         else
  131.         {
  132.             if (pchFile[0] == '\\')
  133.             {
  134.                 getcwd(ptf->achFile, _FNLEN);
  135.                 ptf->achFile[2] = '\0';
  136.                 strcat(ptf->achFile, pchFile);
  137.             }
  138.             else
  139.             {
  140.                 getcwd(ptf->achFile, _FNLEN);
  141.                 if (ptf->achFile[strlen(ptf->achFile) - 1] != '\\')
  142.                     strcat(ptf->achFile, "\\");
  143.                 strcat(ptf->achFile, pchFile);
  144.             }
  145.         }
  146.     }
  147.     else
  148.     {
  149.         strcpy(ptf->achFile, pchFile);
  150.     }
  151.     ptf->nMode = nMode;
  152.     ptf->nAccess = nAccess;
  153.     id = SendMessage(hwndManager, TKWM_OPEN, 0, (LPARAM) ptf);
  154.     if (id == -1)
  155.         return -1;
  156.     _files[ifd].tf_cnt = 1;
  157.     _files[ifd].tf_id = id;
  158.     _files[ifd].tf_dev = iDevice;
  159.     pt->files[fd] = ifd;
  160.     return fd;
  161. }
  162.  
  163. long far _export
  164. tkern_seek(    int    fd,
  165.         long    nPosition,
  166.         int    nStart)
  167. {
  168.     struct    task *pt;
  169.  
  170.     pt = GetTaskInfo();
  171.     if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
  172.     {
  173.         pt->nError = EBADF;
  174.         return -1;
  175.     }
  176.     ptf->iDevice = _files[pt->files[fd]].tf_dev;
  177.     ptf->iTask = (pt - _tasks);
  178.     ptf->nPosition = nPosition;
  179.     ptf->nFrom = nStart;
  180.     return SendMessage(hwndManager, TKWM_SEEK,
  181.                     _files[pt->files[fd]].tf_id,
  182.                     (LPARAM) ptf);
  183. }
  184.  
  185. int far _export
  186. tkern_read(    int    fd,
  187.         char    *pchBuffer,
  188.         int    nBytes)
  189. {
  190.     struct    task *pt;
  191.     LRESULT    nRead;
  192.     int    nTotal = 0;
  193.     int    nNow;
  194.  
  195.     pt = GetTaskInfo();
  196.     if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
  197.     {
  198.         pt->nError = EBADF;
  199.         return -1;
  200.     }
  201.     if (nBytes < 0)
  202.     {
  203.         pt->nError = EINVAL;
  204.         return -1;
  205.     }
  206.     if (_files[pt->files[fd]].tf_eof)
  207.     {
  208.         _files[pt->files[fd]].tf_eof = 0;
  209.         return 0;
  210.     }
  211.     while(1)
  212.     {
  213.         /*
  214.          * We set this structure up inside the loop because it is shared among
  215.          * tasks, and if we end up sleeping, another task may overwrite this
  216.          */
  217.         nNow = nBytes;
  218.         if (nNow > _FBUFSZ)
  219.             nNow = _FBUFSZ;
  220.         ptf->iDevice = _files[pt->files[fd]].tf_dev;
  221.         ptf->iTask = (pt - _tasks);
  222.         ptf->nBytes = nNow;
  223.         nRead = SendMessage(hwndManager, TKWM_READ,
  224.                     _files[pt->files[fd]].tf_id,
  225.                     (LPARAM) ptf);
  226.         if (nRead == -1)
  227.         {
  228.             return -1;
  229.         }
  230.         if (nRead != FR_NOTREADY)
  231.         {
  232.             nTotal += (int) nRead;
  233.             nBytes -= (int) nRead;
  234.             memcpy(pchBuffer, ptf->achBuffer, (int) nRead);
  235.             pchBuffer += (int) nRead;
  236.             if (!nBytes || !nRead)
  237.             {
  238.                 if (nTotal && !nRead)
  239.                     _files[pt->files[fd]].tf_eof = 1;
  240.                 return nTotal;
  241.             }
  242.         }
  243.         else if (nTotal)
  244.         {
  245.             return nTotal;
  246.         }
  247.         else
  248.         {
  249.             GetMessages(pt);
  250.         }
  251.     }
  252. }
  253.  
  254. int far _export
  255. tkern_write(    int    fd,
  256.         char const *pchBuffer,
  257.         int    nBytes)
  258. {
  259.     struct    task *pt;
  260.     int    nTotal = 0;
  261.     int    nWritten;
  262.     int    nNow;
  263.  
  264.     pt = GetTaskInfo();
  265.     if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
  266.     {
  267.         pt->nError = EBADF;
  268.         return -1;
  269.     }
  270.     if (nBytes < 0)
  271.     {
  272.         pt->nError = EINVAL;
  273.         return -1;
  274.     }
  275.     while (nBytes)
  276.     {
  277.         nNow = nBytes;
  278.         if (nNow > _FBUFSZ)
  279.             nNow = _FBUFSZ;
  280.         ptf->iDevice = _files[pt->files[fd]].tf_dev;
  281.         ptf->iTask = (pt - _tasks);
  282.         memcpy(ptf->achBuffer, pchBuffer, nNow);
  283.         ptf->nBytes = nNow;
  284.         nWritten = (int) SendMessage(hwndManager, TKWM_WRITE,
  285.                         _files[pt->files[fd]].tf_id,
  286.                         (LPARAM) ptf);
  287.         if (nWritten == -1)
  288.             return -1;
  289.         if (nWritten != FR_NOTREADY)
  290.         {
  291.             nTotal += (int) nWritten;
  292.             nBytes -= (int) nWritten;
  293.             pchBuffer += (int) nWritten;
  294.             if (!nBytes || !nWritten)
  295.                 return nTotal;
  296.         }
  297.         else
  298.         {
  299.             GetMessages(pt);
  300.         }
  301.     }
  302.     return nTotal;
  303. }
  304.  
  305. int far _export
  306. tkern_close(    int    fd)
  307. {
  308.     struct    task *pt;
  309.     int    ifd;
  310.  
  311.     pt = GetTaskInfo();
  312.     if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
  313.     {
  314.         pt->nError = EBADF;
  315.         return -1;
  316.     }
  317.     ifd = pt->files[fd];
  318.     pt->files[fd] = -1;
  319.     if (!--_files[ifd].tf_cnt)
  320.     {
  321.         _files[ifd].tf_eof = 0;
  322.         ptf->iTask = (pt - _tasks);
  323.         ptf->iDevice = _files[ifd].tf_dev;
  324.         return SendMessage(hwndManager, TKWM_CLOSE,
  325.                         _files[ifd].tf_id,
  326.                         (LPARAM) ptf);
  327.     }
  328.     else
  329.         return 0;
  330. }
  331.  
  332. void
  333. internal_close(    int    fd,
  334.         int    iTask)
  335. {
  336.     int    ifd;
  337.  
  338.     ifd = _tasks[iTask].files[fd];
  339.     _tasks[iTask].files[fd] = -1;
  340.     if (!--_files[ifd].tf_cnt)
  341.     {
  342.         ptf->iDevice = _files[ifd].tf_dev;
  343.         ptf->iTask = iTask;
  344.         SendMessage(    hwndManager,
  345.                 TKWM_CLOSE,
  346.                 _files[ifd].tf_id,
  347.                 (LPARAM) ptf);
  348.     }
  349. }
  350.  
  351. int far _export
  352. tkern_dup(int    fd_in)
  353. {
  354.     struct    task *pt;
  355.     int    fd;
  356.  
  357.     pt = GetTaskInfo();
  358.     if (fd_in < 0 || fd_in >= UFILE_MAX || pt->files[fd_in] == -1)
  359.     {
  360.         pt->nError = EBADF;
  361.         return -1;
  362.     }
  363.     for (fd = 0; fd < UFILE_MAX; fd++)
  364.     {
  365.         if (pt->files[fd] == -1)
  366.         {
  367.             pt->files[fd] = pt->files[fd_in];
  368.             _files[pt->files[fd]].tf_cnt++;
  369.             return fd;
  370.         }
  371.     }
  372.     pt->nError = EMFILE;
  373.     return -1;
  374. }
  375.  
  376. int far _export
  377. tkern_dup2(    int    fd_in,
  378.         int    fd)
  379. {
  380.     struct    task *pt;
  381.  
  382.     pt = GetTaskInfo();
  383.     if (fd_in < 0 || fd_in >= UFILE_MAX ||
  384.         fd < 0 || fd >= UFILE_MAX || pt->files[fd_in] == -1)
  385.     {
  386.         pt->nError = EBADF;
  387.         return -1;
  388.     }
  389.     if (pt->files[fd] != -1)
  390.         internal_close(fd, pt - _tasks);
  391.     pt->files[fd] = pt->files[fd_in];
  392.     _files[pt->files[fd]].tf_cnt++;
  393.     return fd;
  394. }
  395.  
  396. int far _export
  397. tkern_pipe(int    *pfd)
  398. {
  399.     if ((pfd[0] = tkern_open("/dev/pipe/input", 0, 0)) == -1)
  400.         return -1;
  401.     if ((pfd[1] = tkern_open("/dev/pipe/output", 0, 0)) == -1)
  402.     {
  403.         tkern_close(pfd[0]);
  404.         return -1;
  405.     }
  406.     return 0;
  407. }
  408.  
  409. int far _export
  410. tkern_isatty(int    fd)
  411. {
  412.     struct    task *pt;
  413.  
  414.     pt = GetTaskInfo();
  415.     if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
  416.     {
  417.         pt->nError = EBADF;
  418.         return -1;
  419.     }
  420.  
  421.     ptf->iTask = (pt - _tasks);
  422.     ptf->iDevice = _files[pt->files[fd]].tf_dev;
  423.     return SendMessage(hwndManager, TKWM_ISATTY,
  424.                     _files[pt->files[fd]].tf_id,
  425.                     (LPARAM) ptf);
  426. }
  427.  
  428. int    far _export
  429. tkern_ioctl(    int    fd,
  430.         long    nIOCtl,
  431.         char    *pchBuffer)
  432. {
  433.     int    nSize = ((nIOCtl & TK_IOCTL_PARM_SIZE) >> 16);
  434.     int    iReturn = 0;
  435.     int    ifd;
  436.     struct    task *pt;
  437.  
  438.     pt = GetTaskInfo();
  439.     if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
  440.     {
  441.         pt->nError = EBADF;
  442.         return -1;
  443.     }
  444.     ifd = pt->files[fd];
  445.     if (nIOCtl & TK_IOCTL_READ_STRING)
  446.     {
  447.         strncpy(ptf->tki.achBuffer, pchBuffer, nSize - 1);
  448.         ptf->tki.achBuffer[nSize - 1] = 0;
  449.     }
  450.     else if (nIOCtl & TK_IOCTL_READ_INT)
  451.     {
  452.         memcpy(ptf->tki.achBuffer, pchBuffer, nSize);
  453.     }
  454.     ptf->iDevice = _files[ifd].tf_dev;
  455.     ptf->tki.nIOCtl = nIOCtl;
  456.     ptf->tki.nSize = nSize;
  457.     iReturn = SendMessage(hwndManager, TKWM_IOCTL, _files[ifd].tf_id, (LPARAM) ptf);
  458.     if (iReturn != -1)
  459.     {
  460.         nSize = ptf->tki.nSize;
  461.         if (nIOCtl & TK_IOCTL_WRITE_STRING)
  462.         {
  463.             strncpy(pchBuffer, ptf->tki.achBuffer, nSize - 1);
  464.             pchBuffer[nSize - 1] = 0;
  465.         }
  466.         else if (nIOCtl & TK_IOCTL_WRITE_INT)
  467.         {
  468.             memcpy(pchBuffer, ptf->tki.achBuffer, nSize);
  469.         }
  470.     }
  471.     return iReturn;
  472. }
  473.  
  474. int far _export
  475. tkern_is_device(int    fd,
  476.         char const *pchDevice)
  477. {
  478.     struct    task *pt;
  479.     int    ifd;
  480.     int    iDevice;
  481.  
  482.     pt = GetTaskInfo();
  483.     if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
  484.     {
  485.         pt->nError = EBADF;
  486.         return -1;
  487.     }
  488.     ifd = pt->files[fd];
  489.     strcpy(ptf->achFile, pchDevice);
  490.     iDevice = SendMessage(hwndManager, TKWM_GETDEVNO, 0, (LPARAM) ptf);
  491.     return (_files[ifd].tf_dev == iDevice);
  492. }
  493.  
  494. void
  495. files_init(void)
  496. {
  497.     memset(_files, 0, sizeof(_files));
  498.     hTFMem = GlobalAlloc(GMEM_FIXED | GMEM_SHARE, sizeof(*ptf));
  499.     ptf = (struct tfunc *) GlobalLock(hTFMem);
  500.  
  501. }
  502.  
  503. void
  504. files_cleanup(void)
  505. {
  506.     GlobalUnlock(hTFMem);
  507.     GlobalFree(hTFMem);
  508. }
  509.  
  510. int    far _export
  511. tkern_valid_file(int fd)
  512. {
  513.     struct    task *pt;
  514.  
  515.     pt = GetTaskInfo();
  516.     return (pt->files[fd] != -1);
  517. }
  518.  
  519.  
  520.